home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
v9n10.arc
/
THREADS1.ARC
/
THREADS1.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-04-27
|
12KB
|
370 lines
/*----------------------------------------------------------------
THREADS1.C -- Demonstrates off-screen drawing in second thread
(c) 1990, Ziff Communications Co.
PC Magazine * Charles Petzold, 1/89
----------------------------------------------------------------*/
#define INCL_GPI
#define INCL_DOSPROCESS
#include <os2.h>
#include <mt\process.h>
#include <mt\stdlib.h>
#include <mt\string.h>
#define FONTNAME "Tms Rmn Bold"
#define XFONTSIZE 500 // in points
#define YFONTSIZE 500
#define TEXT "PC"
#define TEXTLEN (LONG) strlen (TEXT)
#define BKGNDCOLOR CLR_BLUE
#define DIVISIONS 64 // number of spline areas
#define LCID_FONT 1L
#define ID_PATH 1L
#define STACKSIZE (4096 * sizeof (int))
#define RGB(r,g,b) (((LONG) (r) << 16) | ((g) << 8) | (b))
#define WM_BITMAP_CREATED (WM_USER + 0)
typedef struct
{
int aiThreadStack[STACKSIZE / sizeof (int)] ;
HBITMAP hbm ;
HWND hwndNotify ;
}
THREADPARAMS ;
MPARAM EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM) ;
VOID FAR SecondThread (THREADPARAMS *) ;
HBITMAP CreateBitmap (HAB) ;
VOID DrawImage (HPS, SIZEL *) ;
LONG CreateVectorFont (HPS, LONG, CHAR *) ;
VOID Message (HWND, SHORT, CHAR *) ;
int main (void)
{
static CHAR szClientClass[] = "Threads1" ;
static ULONG flFrameFlags = FCF_TITLEBAR | FCF_SYSMENU |
FCF_SIZEBORDER | FCF_MINMAX |
FCF_SHELLPOSITION | FCF_TASKLIST ;
HAB hab ;
HMQ hmq ;
HWND hwndFrame, hwndClient ;
QMSG qmsg ;
hab = WinInitialize (0) ;
hmq = WinCreateMsgQueue (hab, 0) ;
WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0) ;
hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE,
&flFrameFlags, szClientClass, NULL,
0L, NULL, 0, &hwndClient) ;
while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
WinDispatchMsg (hab, &qmsg) ;
WinDestroyWindow (hwndFrame) ;
WinDestroyMsgQueue (hmq) ;
WinTerminate (hab) ;
return 0 ;
}
MPARAM EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
{
static BOOL fError = FALSE ;
static HBITMAP hbm ;
BITMAPINFOHEADER bmp ;
HPS hps ;
POINTL ptl ;
RECTL rclClient ;
THREADPARAMS *ptp ;
switch (msg)
{
case WM_CREATE:
// allocate memory for thread structure
if ((ptp = malloc (sizeof (THREADPARAMS))) == NULL)
{
Message (hwnd, MB_ICONEXCLAMATION,
"Cannot allocate memory for thread!") ;
return 0 ;
}
ptp->hwndNotify = hwnd ;
// start the thread
if (_beginthread (SecondThread, ptp->aiThreadStack,
STACKSIZE, ptp) == -1)
{
free (ptp) ;
Message (hwnd, MB_ICONEXCLAMATION,
"Cannot create print thread!") ;
return 0 ;
}
return 0 ;
case WM_BITMAP_CREATED:
ptp = PVOIDFROMMP (mp1) ;
hbm = ptp->hbm ;
free (ptp) ;
if (hbm == NULL)
fError = TRUE ;
WinInvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
case WM_PAINT:
hps = WinBeginPaint (hwnd, NULL, NULL) ;
WinQueryWindowRect (hwnd, &rclClient) ;
if (fError == TRUE)
WinDrawText (hps, -1,
"Error occurred during bitmap creation.",
&rclClient, 0L, 0L, DT_CENTER | DT_VCENTER |
DT_TEXTATTRS | DT_ERASERECT) ;
else if (hbm == NULL)
WinDrawText (hps, -1,
"Bitmap being created....",
&rclClient, 0L, 0L, DT_CENTER | DT_VCENTER |
DT_TEXTATTRS | DT_ERASERECT) ;
else
{
WinFillRect (hps, &rclClient, BKGNDCOLOR) ;
GpiQueryBitmapParameters (hbm, &bmp) ;
ptl.x = (rclClient.xRight - bmp.cx) / 2 ;
ptl.y = (rclClient.yTop - bmp.cy) / 2 ;
WinDrawBitmap (hps, hbm, NULL, &ptl, 0L, 0L, DBM_NORMAL) ;
}
WinEndPaint (hps) ;
return 0 ;
case WM_DESTROY:
if (hbm != NULL)
GpiDeleteBitmap (hbm) ;
return 0 ;
}
return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
}
VOID FAR SecondThread (THREADPARAMS *ptp)
{
HAB hab ;
hab = WinInitialize (0) ;
ptp->hbm = CreateBitmap (hab) ; // create bitmap
DosEnterCritSec () ;
WinPostMsg (ptp->hwndNotify, WM_BITMAP_CREATED, // post message
MPFROMP (ptp), NULL) ;
WinTerminate (hab) ;
_endthread () ;
}
HBITMAP CreateBitmap (HAB hab)
{
BITMAPINFOHEADER bmp ;
HBITMAP hbm ;
HDC hdcMemory ;
HPS hpsMemory ;
LONG alBitmapFormat[2] ;
POINTL aptlTextBox[TXTBOX_COUNT] ;
SIZEF sizfx ;
SIZEL sizl ;
// create memory presentation space
hdcMemory = DevOpenDC (hab, OD_MEMORY, "*", 0L, NULL, NULL) ;
sizl.cx = 0 ;
sizl.cy = 0 ;
hpsMemory = GpiCreatePS (hab, hdcMemory, &sizl,
PU_TWIPS | GPIF_DEFAULT |
GPIT_MICRO | GPIA_ASSOC) ;
// create font, select it in PS, and size it
CreateVectorFont (hpsMemory, LCID_FONT, FONTNAME) ;
GpiSetCharSet (hpsMemory, LCID_FONT) ;
sizfx.cx = MAKEFIXED (XFONTSIZE * 20, 0) ;
sizfx.cy = MAKEFIXED (YFONTSIZE * 20, 0) ;
GpiSetCharBox (hpsMemory, &sizfx) ;
// obtain text dimensions and delete font
GpiQueryTextBox (hpsMemory, TEXTLEN, TEXT, TXTBOX_COUNT, aptlTextBox) ;
GpiSetCharSet (hpsMemory, LCID_DEFAULT) ;
GpiDeleteSetId (hpsMemory, LCID_FONT) ;
// convert text dimensions to device coordinates
sizl.cx = aptlTextBox[TXTBOX_CONCAT].x ;
sizl.cy = aptlTextBox[TXTBOX_TOPLEFT].y -
aptlTextBox[TXTBOX_BOTTOMLEFT].y ;
GpiConvert (hpsMemory, CVTC_PAGE, CVTC_DEVICE, 1L, (PPOINTL) &sizl) ;
// create bitmap and set it in the PS
GpiQueryDeviceBitmapFormats (hpsMemory, 2L, alBitmapFormat) ;
bmp.cbFix = 12 ;
bmp.cx = (SHORT) sizl.cx ;
bmp.cy = (SHORT) sizl.cy ;
bmp.cPlanes = (SHORT) alBitmapFormat[0] ;
bmp.cBitCount = (SHORT) alBitmapFormat[1] ;
hbm = GpiCreateBitmap (hpsMemory, &bmp, 0L, NULL, NULL) ;
// convert bitmap size back to page coordinates
GpiConvert (hpsMemory, CVTC_DEVICE, CVTC_PAGE, 1L, (PPOINTL) &sizl) ;
// draw the text on the bitmap
if (hbm != NULL)
{
GpiSetBitmap (hpsMemory, hbm) ;
DrawImage (hpsMemory, &sizl) ;
GpiSetBitmap (hpsMemory, NULL) ;
}
// clean up
GpiDestroyPS (hpsMemory) ;
DevCloseDC (hdcMemory) ;
return hbm ;
}
VOID DrawImage (HPS hps, SIZEL *psizl)
{
INT i ;
LONG lColor ;
POINTL ptl, aptl[8], aptlTextBox[TXTBOX_COUNT] ;
SIZEF sizfx ;
// color the background
GpiSetColor (hps, BKGNDCOLOR) ;
ptl.x = 0 ;
ptl.y = 0 ;
GpiMove (hps, &ptl) ;
ptl.x = psizl->cx ;
ptl.y = psizl->cy ;
GpiBox (hps, DRO_FILL, &ptl, 0L, 0L) ;
// create font, select it in PS, and size it
CreateVectorFont (hps, LCID_FONT, FONTNAME) ;
GpiSetCharSet (hps, LCID_FONT) ;
sizfx.cx = MAKEFIXED (XFONTSIZE * 20, 0) ;
sizfx.cy = MAKEFIXED (YFONTSIZE * 20, 0) ;
GpiSetCharBox (hps, &sizfx) ;
// create clipping path based on text outline
GpiBeginPath (hps, ID_PATH) ;
GpiQueryTextBox (hps, TEXTLEN, TEXT, TXTBOX_COUNT, aptlTextBox) ;
ptl.x = 0 ;
ptl.y = -aptlTextBox[TXTBOX_BOTTOMLEFT].y ;
GpiCharStringAt (hps, &ptl, TEXTLEN, TEXT) ;
GpiEndPath (hps) ;
GpiSetClipPath (hps, ID_PATH, SCP_AND | SCP_ALTERNATE) ;
// switch to RGB colors
GpiCreateLogColorTable (hps, 0L, LCOLF_RGB, 0L, 0L, NULL) ;
for (i = 0 ; i < DIVISIONS ; i++)
{
// set the color
if (i < DIVISIONS / 2)
lColor = RGB (i * 512 / DIVISIONS, 0, 0) ;
else
lColor = RGB (255, i * 512 / DIVISIONS - 256,
i * 512 / DIVISIONS - 256) ;
GpiSetColor (hps, lColor) ;
// define coordinates for spline curves
aptl[0].x = 0 ;
aptl[0].y = i * psizl->cy / DIVISIONS ;
aptl[1].x = psizl->cx / 4 ;
aptl[1].y = aptl[0].y + psizl->cy / 2 ;
aptl[2].x = 3 * psizl->cx / 4 ;
aptl[2].y = aptl[0].y - psizl->cy / 2 ;
aptl[3].x = psizl->cx ;
aptl[3].y = aptl[0].y ;
aptl[4].x = psizl->cx ;
aptl[4].y = (i + 1) * psizl->cy / DIVISIONS ;
aptl[5].x = 3 * psizl->cx / 4 ;
aptl[5].y = aptl[4].y - psizl->cy / 2 ;
aptl[6].x = psizl->cx / 4 ;
aptl[6].y = aptl[4].y + psizl->cy / 2 ;
aptl[7].x = 0 ;
aptl[7].y = aptl[4].y ;
// draw the curves in an area bracket
GpiBeginArea (hps, BA_NOBOUNDARY | BA_ALTERNATE) ;
GpiMove (hps, aptl) ; // set current position
GpiPolySpline (hps, 3L, aptl + 1) ; // draw one spline
GpiLine (hps, aptl + 4) ; // draw line
GpiPolySpline (hps, 3L, aptl + 5) ; // draw second spline
GpiLine (hps, aptl) ; // line to beginning
GpiEndArea (hps) ;
}
// Clean up
GpiCreateLogColorTable (hps, LCOL_RESET, LCOLF_INDRGB, 0L, 0L, NULL) ;
GpiSetCharSet (hps, LCID_DEFAULT) ;
GpiDeleteSetId (hps, LCID_FONT) ;
}
LONG CreateVectorFont (HPS hps, LONG lcid, CHAR *szFacename)
{
FATTRS fat ;
// set up FATTRS structure
fat.usRecordLength = sizeof fat ;
fat.fsSelection = 0 ;
fat.lMatch = 0 ;
fat.idRegistry = 0 ;
fat.usCodePage = GpiQueryCp (hps) ;
fat.lMaxBaselineExt = 0 ;
fat.lAveCharWidth = 0 ;
fat.fsType = 0 ;
fat.fsFontUse = FATTR_FONTUSE_OUTLINE |
FATTR_FONTUSE_TRANSFORMABLE ;
strcpy (fat.szFacename, szFacename) ;
// create the font
return GpiCreateLogFont (hps, NULL, lcid, &fat) ;
}
VOID Message (HWND hwnd, SHORT sIcon, CHAR *pszMessage)
{
WinMessageBox (HWND_DESKTOP, hwnd, pszMessage, "Thread1",
0, sIcon | MB_OK | MB_MOVEABLE) ;
}